/* Vecmath.

   Copyright (C) 2001, 2002, 2003 Stefan Maierhofer.

   Written by Stefan Maierhofer <sm@cg.tuwien.ac.at>

   This file is part of Vecmath.

   Vecmath is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   Vecmath is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with Vecmath; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */

using System;
using NUnit.Framework;

namespace Vecmath
{

    /// <summary>
    /// Scale3F.
    /// </summary>
    public struct Scale3F
    {

        public static Scale3F Identity = new Scale3F(1,1,1);

        public Scale3F(float x, float y, float z)
        {
            v = new Vec3F(x,y,z);
        }

        public Scale3F(Vec3F shift)
        {
            v = shift;
        }

        public float x { get { return v._x[0]; } }
        public float y { get { return v._x[1]; } }
        public float z { get { return v._x[2]; } }

        public Trafo3F ToTrafo3F()
        {
            return new Trafo3F(
                v._x[0], 0, 0, 0,
                0, v._x[1], 0, 0,
                0, 0, v._x[2], 0,
                0, 0, 0, 1
                );
        }

        public static implicit operator Trafo3F(Scale3F s)
        {
            return s.ToTrafo3F();
        }

        public static Vec3F operator*(Vec3F v, Scale3F t)
        {
            return new Vec3F(
                v._x[0] * t.v._x[0],
                v._x[1] * t.v._x[1],
                v._x[2] * t.v._x[2]
                );
        }

        public static Pnt3F operator*(Pnt3F p, Scale3F t)
        {
            return new Pnt3F(
                p._x[0] * t.v._x[0],
                p._x[1] * t.v._x[1],
                p._x[2] * t.v._x[2]
                );
        }

        public static Ray3F operator*(Ray3F r, Scale3F t)
        {
            return new Ray3F(r.p * t, r.v * t);
        }

        public static Box3F operator*(Box3F b, Scale3F t)
        {
            return new Box3F(b.Lower * t, b.Upper * t);
        }

        public static Trafo3F operator*(Shift3F a, Scale3F b)
        {
            return a.ToTrafo3F() * b.ToTrafo3F();
        }

        public static Trafo3F operator*(Rot3F a, Scale3F b)
        {
            return a.ToTrafo3F() * b.ToTrafo3F();
        }

        internal Vec3F v;

    }


    [TestFixture]
    public class Scale3FTest
    {
        [Test]
        public void MulVec3F()
        {
            Vec3F v = new Vec3F(1,2,3);
            Scale3F t = new Scale3F(1,2,3);
            Assert.AreEqual(new Vec3F(1,4,9), v * t);
        }

        [Test]
        public void MulPnt3F()
        {
            Pnt3F p = new Pnt3F(1,2,3);
            Scale3F t = new Scale3F(1,2,3);
            Assert.AreEqual(new Pnt3F(1,4,9), p * t);
        }

        [Test]
        public void MulBox3F()
        {
            Box3F b = new Box3F(new Pnt3F(-1, -1, -1), new Pnt3F(1,1,1));
            Scale3F t = new Scale3F(1,2,3);
            Assert.AreEqual(
                new Box3F(new Pnt3F(-1, -2, -3), new Pnt3F(1,2,3)),
                b * t
                );
        }
    }

}
